package drds.server.route.shard_algorithm;

import drds.server.config.model.Table;

/**
 * 路由分片函数抽象类 为了实现一个默认的支持范围分片的函数 calcualteRange 重写它以实现自己的范围路由规则
 */
public abstract class AbstractShardAlgorithm implements ShardAlgorithm {

	@Override
	public void init() {
	}

	/**
	 * 返回所有被路由到的节点的编号 返回长度为0的数组表示所有节点都被路由（默认） 返回null表示没有节点被路由到
	 */
	@Override
	public Integer[] calculateRange(String beginColumnValue, String endColumnValue) {
		return new Integer[0];
	}

	/**
	 * 对于存储数据按顺序存放的字段做范围路由，可以使用这个函数
	 */
	public static Integer[] calculateRange(AbstractShardAlgorithm shardAlgorithm, String beginColumnValue, String endColumnValue) {
		Integer begin = 0, end = 0;
		begin = shardAlgorithm.calculate(beginColumnValue);
		end = shardAlgorithm.calculate(endColumnValue);

		if (begin == null || end == null) {
			return new Integer[0];
		}

		if (end >= begin) {
			int length = end - begin + 1;
			Integer[] result = new Integer[length];
			for (int i = 0; i < length; i++) {
				result[i] = begin + i;
			}
			return result;
		} else {
			return new Integer[0];
		}
	}

	/**
	 * 
	 * 分片表所跨的节点数与分片算法分区数一致性校验
	 * 
	 * @param table
	 * @return -1 if table datanode size < rule function partition size 0 if
	 *         table datanode size == rule function partition size 1 if table
	 *         datanode size > rule function partition size
	 */
	public final int suitableFor(Table table) {
		int shardNum = getShardNum();
		if (shardNum > 0) { // 对于有限制分区数的规则,进行检查
			int size = table.getDataNodeList().size();
			if (size < shardNum) {
				return -1;
			} else if (size > shardNum) {
				return 1;
			}
		}
		return 0;
	}

	/**
	 * 返回分区数, 返回-1表示分区数没有限制
	 */
	public int getShardNum() {
		return -1; // 表示没有限制
	}

}
